package com.nd.config;

import cn.hutool.crypto.digest.BCrypt;
import com.nd.realm.AdminRealm;
import com.nd.realm.MallToken;
import com.nd.realm.WxRealm;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Properties;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//        shiroFilterFactoryBean.setLoginUrl("/auth/login/login.js");
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //过滤请求 key 请求url  value 过滤方式
        LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
        //amon代表不用验证直接访问
        filterMap.put("/admin/auth/login","anon");
        filterMap.put("/wx/auth/login","anon");
        filterMap.put("/wx/home/index","anon");
        filterMap.put("/wx/goods/count","anon");
        filterMap.put("/wx/catalog/index","anon");
        filterMap.put("/wx/catalog/current","anon");//当前类目
        filterMap.put("/wx/goods/category","anon");//商品类目
        filterMap.put("/wx/goods/list","anon");//商品列表
        filterMap.put("/wx/goods/detail","anon");//商品详情列表
        filterMap.put("/wx/groupon/list","anon");//团购活动列表
        filterMap.put("/wx/coupon/list","anon");//团购活动列表
        filterMap.put("/wx/brand/list","anon");//品牌商列表
        filterMap.put("/wx/topic/list","anon");//专题列表
        filterMap.put("/wx/storage/upload","anon");//前台图片上传
        filterMap.put("/wx/search/index","anon");//搜索主页
        filterMap.put("/wx/search/helper","anon");//搜索helper
        filterMap.put("/wx/auth/regCaptcha","anon");//用户验证码发短信
        filterMap.put("/wx/auth/register","anon");//用户注册
        filterMap.put("/wx/auth/reset","anon");//用户修改密码
        filterMap.put("/wx/brand/detail","anon");//品牌商详情
        filterMap.put("/wx/comment/list","anon");//评论列表详情
        filterMap.put("/wx/topic/detail","anon");//专题详情
        filterMap.put("/wx/topic/related","anon");//专题相关详情
        //静态资源不过滤
        filterMap.put("/static/**","anon");
        //authc需要登录验证
        filterMap.put("/**","authc");
//        filterMap.put("/need/perm","perms[perm1]");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager(AdminRealm adminRealm,CustomAuthenticator authenticator){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(adminRealm);
        defaultWebSecurityManager.setSessionManager(defaultWebSessionManager());
        defaultWebSecurityManager.setAuthenticator(authenticator);
        return defaultWebSecurityManager;
    }

    @Bean
    //注册admin验证
    public AdminRealm adminRealm(){
        AdminRealm adminRealm = new AdminRealm();
        //匹配密码
        adminRealm.setCredentialsMatcher(new CredentialsMatcher() {
            @Override
            public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
                MallToken token = (MallToken) authenticationToken;
                String password = new String(token.getPassword());
                //从realm类中获取数据库中查询出来的密文密码
                String encodePassword = authenticationInfo.getCredentials().toString();
//              //静态方法,判断传入的明文密码数据库中查询的密文密码是否一致,用的hutool的包
                return BCrypt.checkpw(password,encodePassword);
            }
        });
        return adminRealm;
    }

    @Bean
    public DefaultWebSessionManager defaultWebSessionManager(){
        //默认存入sessionId
        return new AdminSessionManager();
    }


    //声明式鉴权,可以在方法上面使用注解来声明权限
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    //注册前台微信验证
    public WxRealm WxRealm(){
        WxRealm wxRealm = new WxRealm();
        //匹配密码
        wxRealm.setCredentialsMatcher(new CredentialsMatcher() {
            @Override
            public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
                MallToken token = (MallToken) authenticationToken;
                String password = new String(token.getPassword());
                //从realm类中获取数据库中查询出来的密文密码
                String encodePassword = authenticationInfo.getCredentials().toString();
//              //静态方法,判断传入的明文密码数据库中查询的密文密码是否一致,用的hutool的包
                return BCrypt.checkpw(password,encodePassword);
            }
        });
        return wxRealm;
    }
    /*异常映射请求，key 异常类，value 异常处理的请求*/
    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver(){
        SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
        Properties mappings = new Properties();
        mappings.put("org.apache.shiro.authz.AuthorizationException","/noperm");
//        mappings.put("org.springframework.http.converter.HttpMessageNotReadableException","/noperm1");
        simpleMappingExceptionResolver.setExceptionMappings(mappings);
        return simpleMappingExceptionResolver;
    }

    @Bean
    //注册认证器分发realm
    public CustomAuthenticator customAuthenticator(AdminRealm adminRealm,WxRealm wxRealm){
        CustomAuthenticator customAuthenticator = new CustomAuthenticator();
        ArrayList<Realm> realmArrayList = new ArrayList<>();
        realmArrayList.add(adminRealm);
        realmArrayList.add(wxRealm);
        customAuthenticator.setRealms(realmArrayList);
        return customAuthenticator;
    }
}
